<template>
  <div class="upload-excel-container">
    <div
      class="upload-slot"
      :class="{ drag }"
      @click="handleUpload"
      @drop.stop.prevent="handleDrop"
      @dragover.stop.prevent="handleDragover"
      @dragenter.stop.prevent="handleDragover"
    >
      <slot
        ><el-button type="primary" :loading="uploadLoading" v-if="!drag"
          >上传Excel</el-button
        >
        <div v-else class="upload-drag">
          <div class="upload-drag-container">
            <svg-icon icon-class="upload" size="4em" />
            <div>将Excel文件拖到此处</div>
          </div>
        </div>
      </slot>
    </div>
    <input
      type="file"
      ref="uploadInputRef"
      accept=".xlsx, .xls"
      @change="handleChange"
      class="upload-input"
    />
  </div>
</template>

<script setup lang="ts">
import * as XLSX from "xlsx/xlsx.mjs";
import { ref, defineProps } from "vue";
import { getHeaderRow, isExcel } from "./excelUtils";
import { ElMessage } from "element-plus";
import SvgIcon from "@/components/SvgIcon/index.vue";

export interface ISuccessResult {
  header: Array<any>;
  results: Array<any>;
}

const props = defineProps({
  drag: {
    type: Boolean,
    default: false,
  },
  beforeUpload: {
    type: Function,
  },
  onSuccess: {
    type: Function,
  },
});

const uploadInputRef = ref<HTMLInputElement>();
const uploadLoading = ref<Boolean>(false);
/**
 * 点击选择文件
 */
const handleUpload = () => {
  if (props.drag) return;
  uploadInputRef.value?.click();
};

/**
 * 拖拽文本释放时触发
 */
const handleDrop = (e: DragEvent) => {
  // 上传中跳过
  if (uploadLoading.value || !props.drag) return;
  const files = e.dataTransfer?.files;
  if (files?.length !== 1) {
    ElMessage.error("必须要有一个文件");
    return;
  }
  const rawFile = files[0];
  if (!isExcel(rawFile)) {
    ElMessage.error("文件必须是 .xlsx, .xls, .csv 格式");
    return false;
  }
  // 触发上传事件
  upload(rawFile);
};

/**
 * 拖拽悬停时触发
 */
const handleDragover = (e: DragEvent) => {
  // 在新位置生成源项的副本
  if (!props.drag) return;
  e.dataTransfer.dropEffect = "copy";
};

/**
 * 选择文件后
 */
const handleChange = (e: Event) => {
  const files = (e.target as HTMLInputElement).files;
  if (!files || !files.length) return;
  const rawFile = files[0];
  upload(rawFile);
};

/**
 * 触发上传
 * @param {*} file
 */
const upload = (file: any) => {
  // 清空input内容
  uploadInputRef.value.value = null;
  // 如果没有指定上传前回调
  if (!props.beforeUpload) {
    readerData(file);
    return;
  }
  // 如果设置了上传前回调， 返回ture才执行后续逻辑
  const before = props.beforeUpload(file);
  if (before) {
    readerData(file);
  }
};
/**
 * 读取文件数据
 */
const readerData = (file: any) => {
  console.log(file);
  uploadLoading.value = true;
  const reader = new FileReader();
  //  文件读取完成后触发
  reader.onload = (e) => {
    // 1.获取读取到的数据
    const data = e.target?.result;

    // 2.利用XLSX对数据进行解析, cellDates 解析时间
    const workbook = XLSX.read(data, {
      type: "array",
      cellText: false,
      cellDates: true,
    });
    // 3.获取第一张表格的名称
    const firstSheetName = workbook.SheetNames[0];
    // 4.读取第一张表格的数据
    const workSheet = workbook.Sheets[firstSheetName];
    // 5.解析数据表头
    // const header = getHeaderRow(workSheet);
    const allData = XLSX.utils.sheet_to_json(workSheet, { header: 1 });
    const header = allData.length > 0 ? allData[0] : Array(10).fill("");
    // 6.解析数据体
    const results = XLSX.utils.sheet_to_json(workSheet, {
      raw: false,
      dateNF: "YYYY-MM-DD HH:mm:ss",
    });
    // 7.传入解析之后的数据
    generateData({ header, results });
    uploadLoading.value = false;
  };
  // 启动读取指定的文件或者blob
  reader.readAsArrayBuffer(file);
};

const generateData = (excelData: ISuccessResult) => {
  props.onSuccess && props.onSuccess(excelData);
};
</script>

<style lang="scss" scoped>
.upload-excel-container {
  .upload-slot {
    display: inline-block;
    &.drag {
      width: 300px;
      height: 160px;
      display: flex;
      justify-content: center;
      align-items: center;
      border-radius: 6px;
      border: 1px dashed #bbb;
      .upload-drag {
        display: flex;
        justify-content: center;
        align-items: center;
        color: #bbb;
        width: inherit;
        height: inherit;
        font-size: 14px;
        &-container {
          text-align: center;
        }
      }
    }
  }
  .upload-input {
    display: none;
    z-index: -9999;
  }
}
</style>
